package com.sunmouse.okhttplib;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;

import com.squareup.okhttp.Callback;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.MultipartBuilder;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;

import org.json.JSONObject;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * Created by leiyun on 2018/5/9.
 */
public class JsonUtil {

    public static final MediaType TYPE_MP3 = MediaType.parse("audio/mpeg;charset=utf-8");
    public static final MediaType TYPE_JPG = MediaType.parse("image/jpeg;charset=utf-8");
    public static final MediaType TYPE_MP4 = MediaType.parse("video/mpeg;charset=utf-8");

    private final static long CONNECT_TIMEOUT = 10;//unit second
    private final static long READ_TIMEOUT = 10;//unit second

    public static final int SUCCESS = 0;
    public static final int FAIL = 1;
    public static final int PRE_EXECUTE = 2;

    private MultipartBuilder mBuilder;
    private Request.Builder mRequestBuilder;
    private OkHttpClient mClient;
    private static JsonUtil mUtil;
    private String mFlag;
    private JsonHttpResponse mJsonResponse;
    private Handler mHandler;
    private Message mMsg;


    private JsonUtil(Context context) {
        initHandler();
        this.mBuilder = new MultipartBuilder();
        this.mRequestBuilder = new Request.Builder();
        this.mClient = new OkHttpClient();
        this.mClient.setConnectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS);
        this.mClient.setReadTimeout(READ_TIMEOUT, TimeUnit.SECONDS);
    }


    /**
     * init handler
     */
    private void initHandler() {
        if (mHandler == null) {
//            Looper.prepare();
            mHandler = new ResultHandler(Looper.getMainLooper());
//            Looper.loop();
        }
    }

    /**
     * init
     */
    public static JsonUtil init(Context context) {
        if (mUtil == null) mUtil = new JsonUtil(context);
        return mUtil;
    }

    /**
     * set headers
     */
    public JsonUtil headers(HashMap<String, String> headers) {
        if (headers != null) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                this.mRequestBuilder.addHeader(entry.getKey(), getString(entry.getValue()));
            }
        }
        return mUtil;
    }

    public JsonUtil header(String key, String value) {
        if (!TextUtils.isEmpty(key)) {
            this.mRequestBuilder.addHeader(key, getString(value));
        }
        return mUtil;
    }

    /**
     * connect timeout
     */
    public JsonUtil connectTimeout(int timeout) {
        mClient.setConnectTimeout(timeout, TimeUnit.SECONDS);
        return mUtil;
    }

    /**
     * read  timeout
     */
    public JsonUtil readTimeout(int timeout) {
        mClient.setReadTimeout(timeout, TimeUnit.SECONDS);
        return mUtil;
    }

    /**
     * set url
     */
    public JsonUtil url(String url) {
        if (TextUtils.isEmpty(url)) {
            throw new RuntimeException("Error:url is null");
        }
        mRequestBuilder.url(url);
        return mUtil;
    }

    public JsonUtil flag(String flag) {
        this.mFlag = flag;
        return mUtil;
    }


    /**
     * set params
     */
    public JsonUtil params(HashMap<String, String> params) {
        if (params != null) {
            for (Map.Entry<String, String> entry : params.entrySet()) {
                this.mBuilder.addFormDataPart(entry.getKey(), getString(entry.getValue()));
            }
        }
        return mUtil;
    }

    /**
     * set single params
     */
    public JsonUtil param(String key, String value) {
        if (!TextUtils.isEmpty(key)) mBuilder.addFormDataPart(key, getString(value));
        return mUtil;
    }

    /**
     * set file
     */
    public JsonUtil audio(String key, File file) {
        if (file != null) {
            mBuilder.addFormDataPart(key, file.getName(), RequestBody.create(TYPE_MP3, file));
        }
        return mUtil;
    }

    /**
     * set file
     */
    public JsonUtil video(String key, File file) {
        if (file != null) {
            mBuilder.addFormDataPart(key, file.getName(), RequestBody.create(TYPE_MP4, file));
        }
        return mUtil;
    }


    /**
     * post
     */
    public synchronized void post(JsonHttpResponse ck) {
        this.mJsonResponse = ck;
        initHandler();
        sendMsg(PRE_EXECUTE, null);
        this.mRequestBuilder.post(mBuilder.build());
        this.mClient.newCall(mRequestBuilder.build())
                .enqueue(new ResultCallback());
    }

    /**
     * get
     */
    public void get(JsonHttpResponse ck) {
        this.mJsonResponse = ck;
        initHandler();
        sendMsg(PRE_EXECUTE, null);
        this.mClient.newCall(mRequestBuilder.build())
                .enqueue(new ResultCallback());
    }

    /**
     * get String
     */
    private String getString(String src) {
        if (TextUtils.isEmpty(src)) return "";
        return src;
    }


    /**
     * mResult handle
     */
    class ResultHandler extends Handler {

        public ResultHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case PRE_EXECUTE:
                    if (mJsonResponse != null) mJsonResponse.onPreExecute(mFlag);
                    break;
                case SUCCESS:
                    if (mJsonResponse != null)
                        mJsonResponse.onSuccess((JSONObject) msg.obj, mFlag);
                    break;
                case FAIL:
                    if (mJsonResponse != null)
                        mJsonResponse.onFailure((Exception) msg.obj, mFlag);
                    break;
            }
        }
    }

    /**
     * result ck
     */
    class ResultCallback implements Callback {

        @Override
        public void onFailure(Request request, IOException e) {
            sendMsg(FAIL, e);
        }

        @Override
        public void onResponse(Response response) throws IOException {
            String result = response.body().string();
//            sendMsg(SUCCESS, StringUtils.isJSONObject(result) ? StringUtils.getJSONObject() : null);
        }
    }

    /**
     * send message
     *
     * @param what
     * @param obj
     */
    private void sendMsg(int what, Object obj) {
        mMsg = Message.obtain();
        mMsg.what = what;
        mMsg.obj = obj;
        mHandler.sendMessage(mMsg);
    }


}
